import 'dart:developer';
import 'package:flutter/foundation.dart';
import '../utils/errors.dart';


class ErrorHandler {
  static final ErrorHandler _instance = ErrorHandler._internal();

  factory ErrorHandler() => _instance;

  ErrorHandler._internal();

  
  void handleError(
    dynamic error,
    String context,
    {bool rethrowError = false}
  ) {
    
    if (error is AppError) {
      _logError(error, context);
      if (rethrowError) {
        throw error;
      }
      return;
    }

    
    final appError = _convertToAppError(error);
    _logError(appError, context);

    if (rethrowError) {
      throw appError;
    }
  }

  
  AppError _convertToAppError(dynamic error) {
    if (error == null) {
      return AppError(
        message: '未知错误',
        type: AppErrorType.unknown,
      );
    }

    
    final errorMessage = error.toString().toLowerCase();
    AppErrorType type = AppErrorType.unknown;
    
    
    if (errorMessage.contains('database') || 
        errorMessage.contains('sqflite') ||
        errorMessage.contains('lock')) {
      type = AppErrorType.database;
    } else if (errorMessage.contains('timeout')) {
      type = AppErrorType.timeout;
    } else if (errorMessage.contains('validation') ||
               errorMessage.contains('invalid') ||
               errorMessage.contains('format')) {
      type = AppErrorType.validation;
    } else if (errorMessage.contains('permission') ||
               errorMessage.contains('denied')) {
      type = AppErrorType.permission;
    } else if (errorMessage.contains('exception')) {
      type = AppErrorType.business;
    }

    return AppError(
      message: error.toString(),
      type: type,
      cause: error,
      stackTrace: StackTrace.current,
    );
  }

  
  void _logError(AppError error, String context) {
    
    if (kDebugMode) {
      log(
        '[$error.type] $error.message',
        name: 'AppError',
        error: error.cause,
        stackTrace: error.stackTrace,
        level: _getLogLevel(error.type),
      );
      log('错误上下文: $context', name: 'AppContext');
    } else {
      
      log(
        '[$error.type] $error.message',
        name: 'AppError',
        level: _getLogLevel(error.type),
      );
    }
  }

  
  int _getLogLevel(AppErrorType type) {
    switch (type) {
      case AppErrorType.database:
      case AppErrorType.timeout:
      case AppErrorType.validation:
      case AppErrorType.network:
        return 800; 

      case AppErrorType.permission:
        return 900; 

      default:
        return 1000; 

    }
  }

  
  AppError createDatabaseError(String message, {dynamic originalError}) {
    return AppError(
      message: message,
      type: AppErrorType.database,
      cause: originalError,
      isRecoverable: false,
      stackTrace: StackTrace.current,
    );
  }

  AppError createNetworkError(String message, {dynamic originalError}) {
    return AppError(
      message: message,
      type: AppErrorType.network,
      cause: originalError,
      isRecoverable: true,
      stackTrace: StackTrace.current,
    );
  }

  AppError createValidationError(String message) {
    return AppError(
      message: message,
      type: AppErrorType.validation,
      cause: null,
      isRecoverable: true,
      stackTrace: StackTrace.current,
    );
  }

  

  
  String getUserFriendlyMessage(AppError error) {
    switch (error.type) {
      case AppErrorType.database:
        return '数据库错误，请重启应用重试';
      case AppErrorType.storage:
        return '存储错误，请检查存储空间';
      case AppErrorType.validation:
        return error.message;
      case AppErrorType.permission:
        return '权限不足，请在设置中允许相关权限';
      case AppErrorType.business:
        return error.message;
      case AppErrorType.network:
        return '网络连接异常，请检查网络设置后重试';
      case AppErrorType.timeout:
        return '请求超时，请检查网络连接后重试';
      case AppErrorType.unknown:
      default:
        return '发生意外错误，请稍后重试';
    }
  }

  
  Future<T> wrap<T>(
    Future<T> Function() operation,
    {String operationName = 'operation',
    bool rethrowError = false}
  ) async {
    return safeOperation(
      operation,
      operationName,
      rethrowError: rethrowError
    );
  }

  
  Future<T> safeOperation<T>(
    Future<T> Function() operation,
    String operationName,
    {T Function()? fallbackValue,
    bool rethrowError = false}
  ) async {
    try {
      return await operation();
    } catch (e) {
      final appError = _convertToAppError(e);
      _logError(appError, operationName);

      if (fallbackValue != null) {
        return fallbackValue();
      }

      if (rethrowError) {
        throw appError;
      }

      rethrow;
    }
  }
}


extension SafeFuture<T> on Future<T> {
  Future<T> safeOperation(
    String operationName,
    {T Function()? fallbackValue,
    bool rethrowError = false}
  ) {
    return ErrorHandler().safeOperation(
      () => this,
      operationName,
      fallbackValue: fallbackValue,
      rethrowError: rethrowError,
    );
  }
}
